package main

// 测试读写json文件
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strconv"
	"time"
)

const filename = "data.json"

type Council struct {
	NodeId   string
	NodeAddr string
}

// 测试json 文件写入
func main1() {
	info := []Council{{"N0", "127.0.0.1:5000"}, {"N1", "127.0.0.1:5001"}}
	// 创建文件
	filePtr, err := os.Create("info.json")
	if err != nil {
		fmt.Println("文件创建失败", err.Error())
		return
	}
	defer filePtr.Close()
	// 创建Json编码器
	encoder := json.NewEncoder(filePtr)
	err = encoder.Encode(info)
	if err != nil {
		fmt.Println("编码错误", err.Error())
	} else {
		fmt.Println("编码成功")
	}
}

// func main2() {
// 	filePtr, err := os.Open("./info.json")
// 	if err != nil {
// 		fmt.Println("文件打开失败 [Err:%s]", err.Error())
// 		return
// 	}
// 	defer filePtr.Close()
// 	var info []Website
// 	// 创建json解码器
// 	decoder := json.NewDecoder(filePtr)
// 	err = decoder.Decode(&info)
// 	if err != nil {
// 		fmt.Println("解码失败", err.Error())
// 	} else {
// 		fmt.Println("解码成功")
// 		fmt.Println(info)
// 	}
// }

func HandleJson(jsonFile, nodeid, nodeaddr string, num int) error {
	// Read json buffer from jsonFile
	byteValue, err := ioutil.ReadFile(jsonFile)
	if err != nil {
		return err
	}

	// We have known the outer json object is a map, so we define  result as map.
	// otherwise, result could be defined as slice if outer is an array
	var result map[string]interface{}
	err = json.Unmarshal(byteValue, &result)
	if err != nil {
		return err
	}

	// handle peers
	flag := false
	nodes := result["nodes"].([]interface{})
	for _, node := range nodes {
		m := node.(map[string]interface{})
		if name, exists := m["Group"]; exists {
			if name == strconv.Itoa(num) {
				m["nodeid"] = nodeid
				m["nodeaddr"] = nodeaddr
				flag = true
				break
			}
		}
	}
	if !flag {
		fmt.Println("append")
		mm := map[string]interface{}{
			"Group":    strconv.Itoa(num),
			"nodeid":   nodeid,
			"nodeaddr": nodeaddr,
		}
		nodes = append(nodes, mm)
		result["nodes"] = nodes
	}

	// Convert golang object back to byte
	byteValue, err = json.Marshal(result)
	if err != nil {
		return err
	}

	// Write back to file
	err = ioutil.WriteFile(jsonFile, byteValue, 0644)
	return err
}

type Nonmsg struct {
	Node      NodeInfo
	Timestamp int64
}

type NodeInfo struct {
	ID     string
	Addr   string
	Votech bool
}

func main3() {
	r := new(Nonmsg)
	r.Node.ID = "rf.node.ID"
	r.Node.Addr = "127.0.0.1"
	r.Timestamp = time.Now().UnixNano()

	mssg, err := json.Marshal(r)
	if err != nil {
		log.Panic(err)
	}
	fmt.Println("mssg:", string(mssg))
}

func mainjsonprocess() {
	//main1()
	t0 := time.Now()
	HandleJson(filename, "N0", "127.0.0.1:0000", 0)
	fmt.Println("1:", time.Now().Sub(t0))
	HandleJson(filename, "N1", "127.0.0.1:11111", 1)
	HandleJson(filename, "N2", "127.0.0.1:22222", 2)
	HandleJson(filename, "N3", "127.0.0.1:3333", 3)
	HandleJson(filename, "N4", "127.0.0.1:55555", 5)
	HandleJson(filename, "N99", "127.0.0.1:9999", 99)
	fmt.Println("4:", time.Now().Sub(t0))

	// 读配置文件
	var nodeTable map[string]string

	nodeTable = make(map[string]string)
	t1 := time.Now()
	readjson(filename, nodeTable)
	fmt.Println("read:", time.Now().Sub(t1))

	for k, v := range nodeTable {
		fmt.Println("readresult:", k, v)
	}

}

func readjson(jsonFile string, nodetable map[string]string) error {
	byteValue, err := ioutil.ReadFile(jsonFile)
	if err != nil {
		return err
	}

	// We have known the outer json object is a map, so we define  result as map.
	// otherwise, result could be defined as slice if outer is an array
	var result map[string]interface{}
	err = json.Unmarshal(byteValue, &result)
	if err != nil {
		return err
	}
	// for k, v := range result {
	// 	fmt.Println(k, "     ", v)
	// }
	// handle peers
	nodes := result["nodes"].([]interface{})
	for _, node := range nodes {
		m := node.(map[string]interface{})
		if _, exists := m["Group"]; exists {
			nodeid := m["nodeid"].(string)
			nodeaddr := m["nodeaddr"].(string)
			nodetable[nodeid] = nodeaddr
		}
	}
	return nil
}
